var c = document.getElementById('c'),
    ctx = c.getContext('2d');
c.width = window.innerWidth * window.devicePixelRatio;
c.height = window.innerHeight * window.devicePixelRatio;

function Circle(x, y, r, fillColor, strokeColor) {
    this.x = x || 0;
    this.y = y || 0;
    this.r = r || 10;
    this.fillColor = fillColor || 'red';
    this.strokeColor = strokeColor || 'white';
    this.rotation = 0;
}
Circle.prototype = {
    fill: function(ctx) {
        ctx.save();
        ctx.fillStyle = this.fillColor;
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, false);
        ctx.closePath();
        ctx.fill();
        ctx.restore();
    },
    stroke: function(ctx) {
        ctx.save();
        ctx.strokeStyle = this.strokeColor;
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, false);
        ctx.closePath();
        ctx.stroke();
        ctx.restore();
    }
}

/**
 * 直角坐标系中表示一个圆：x^2 + y^2 = r^2，通过推导可得到圆的参数方程：x = r * cosθ， y = r * sinθ
 * 利用参数方程，我们只需要每一帧去改变θ的值就可以实现圆周运动
 */
function perfectCircle() {
    
    var circleTrack= new Circle(c.width / 2, c.height / 2, 100);
    var circle = new Circle(c.width / 2 + 100, c.height / 2, 20);
    
    var tween = new TWEEN.Tween(circleTrack).to({
        rotation: 360
    }, 3000).easing(TWEEN.Easing.Linear.None)
    .repeat(Infinity)
    .onUpdate(function(obj) {
        circleTrack.rotation = obj.rotation;
    
        var newX = circleTrack.r * Math.cos(circleTrack.rotation * Math.PI / 180),
            newY = circleTrack.r * Math.sin(circleTrack.rotation * Math.PI / 180);
    
        circle.x = circleTrack.x + newX;
        circle.y = circleTrack.y + newY;
    }).start();
    
    //动画函数
    function animate() {
        ctx.fillStyle = '#000';
        ctx.fillRect(0, 0, c.width, c.height);
    
        var id = requestAnimationFrame(animate);
        var result = TWEEN.update();
        if(!result) cancelAnimationFrame(id);
    
        circleTrack.stroke(ctx);
        circle.fill(ctx);
    }
    
    animate();
}

/**
 * 椭圆可以理解为在x轴y轴上离圆心距离不同的圆。
 * 标准表达式：(x / a)^2 + (y / b)^2 = 1; 一次推导出椭圆的参数方程为
 * 参数方程： x = a * cosθ, y = b * sinθ;
 */
function createEllipse() {
    function Ellipse(x, y, a, b, colorStroke, colorFill) {
        this.x = x || 0;
        this.y = y || 0;
        this.a = a || 10;
        this.b = b || 10;
        this.rotation = 0;
        this.colorStroke = colorStroke || '#fff';
        this.colorFill = colorFill || '#fff';
        //采用均匀压缩发绘制椭圆，需要额外的属性
        this.r = this.a > this.b ? this.a : this.b;
        this.ratioX = this.a / this.r;
        this.ratioY = this.b / this.r;
    }
    Ellipse.prototype = {
        fill: function(ctx) {
            ctx.save();
            ctx.fillStyle = this.colorFill;
            ctx.scale(this.ratioX, this.ratioY);
            ctx.beginPath();
            ctx.arc(this.x / this.ratioX, this.y / this.ratioY, this.r, 0, Math.PI * 2, false);
            ctx.closePath();
            ctx.fill();
            ctx.restore();
        },
        stroke: function(ctx) {
            ctx.strokeStyle = this.colorStroke;
            ctx.lineWidth = 22;
            ctx.save();
            ctx.scale(this.ratioX, this.ratioY);
            ctx.beginPath();
            ctx.arc(this.x / this.ratioX, this.y / this.ratioY, this.r, 0, Math.PI * 2, false);
            ctx.closePath();
            ctx.restore();
            ctx.stroke();
        }
    }

    var ellipse = new Ellipse(c.width / 2, c.height / 2, 150, 75, 'rgba(234, 234, 234, .01)', 'red');
    var ball = new Circle(c.width / 2 + ellipse.a, c.height / 2, 11, '#00bbff', '#00bbff');

    var tween = new TWEEN.Tween(ellipse).to({
        rotation: 360
    }, 3000)
    .easing(TWEEN.Easing.Linear.None)
    .repeat(Infinity)
    .onUpdate(function(obj) {
        ellipse.rotation = obj.rotation;

        var newX = ellipse.a * Math.cos(ellipse.rotation * Math.PI / 180),
            newY = ellipse.b * Math.sin(ellipse.rotation * Math.PI / 180);

        ball.x = ellipse.x + newX;
        ball.y = ellipse.y + newY;
    }).start();

    //动画函数
    function animate() {
        ctx.fillStyle = 'rgba(0, 0, 0, .1)';
        ctx.fillRect(0, 0, c.width, c.height);

        var id = requestAnimationFrame(animate);
        var result = TWEEN.update();
        if(!result) cancelAnimationFrame(id);
        
        ellipse.stroke(ctx);
        ball.fill(ctx);
    }

    animate();
}

createEllipse();